iT邦幫忙

2021 iThome 鐵人賽

DAY 2
2

相信大家對Fibonacci這個名稱應該都不陌生
就直接來看題目的定義吧!

Given n, calculate F(n).

F(0) = 0, F(1) = 1
F(n) = F(n - 1) + F(n - 2), for n > 1.

fibonacci可以說是認識遞迴最好的題目

看到題目最直覺的想法如下

if n =1:
    return 0;

if n =2:
    return 1;

else:
    return fib(n-1) + fib(n-2)

直接轉換成javascript應該就如下

  function fib(n) {
    if (n === 1) {
      return 0;
    } else if (n === 2) {
      return 1;
    } else {
      return fib(n - 1) + fib(n - 2);
    }
  }

但這種方式我們其實會重複做很多的事

Untitled

從這張圖可以看到
我們在fib(5)呼叫了fib(4)
再計算fib(6)時又會去呼叫fib(4)
當n很大時,重複計算是很耗費時間的!


這時候我們就應該思考
『有辦法減少重複做的事?』
如果我們把已經算好的數都存到hashTable這樣我們就可以以 O(1) 的時間取得我們要的值

就像是查表一樣(有一點Dynamic Programming (DP)的感覺 -> 明天會介紹)
因此,我們可以讓時間複雜度降低到 O(n)
而空間複雜度,我們最多儲存n個數在我們要查的表中,所以space一樣是 O(n)


  function fib(n, table = { 1: 0, 2: 1 }) {
    if (n in table) {
      return table[n];
    } else {
      table[n] = fib(n - 1, table) + fib(n - 2, table);
      return table[n];
    }
  }


既然我們可以降低時間複雜度
我們接著思考
『有沒有辦法再降低空間複雜度?』

我們真的有需要把所有fib(n)的計算結果都存起來嗎?
當我們要算fib(3)其實只需要fib(2)和fib(1)

每一次計算其實都只用前兩個的結果
也就是我們只需要去存當下要算的前面兩個結果
而用不到的就丟到垃圾桶,對吧?
結論-> 我們可以用一個長度為2的陣列來儲存前面兩個結果就好!
來看看實際的做法吧!

Time: O(n),Space: O(1)

var fib = function(n) {
    if (n === 0) return 0;
    if (n === 1) return 1;
    //迷你庫存
    const lastTwo = [1, 1];
    let count = 3;
    while (count <= n) {
    //更新庫存
      const nextFib = lastTwo[0] + lastTwo[1];
      lastTwo[0] = lastTwo[1];
      lastTwo[1] = nextFib;
      count++;
    }
    return lastTwo[1];
  };

看完這些方式,也別忘記自己實做看看喔!
唯有自己Coding過才會知道自己的bug在哪邊!用看的感覺和做起來差很大!!

明日題目預告:
小時候很常被問到的湊錢問題:Coin Change


上一篇
Day 01:前言
下一篇
Day 03 : 我不要很多零錢- Coin Change
系列文
30天用JavaScript刷題刷起來!30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中
1
pjchender
iT邦新手 3 級 ‧ 2021-09-18 01:23:15

好喜歡手繪的風格~

Jen iT邦新手 5 級 ‧ 2021-09-19 16:30:59 檢舉

/images/emoticon/emoticon25.gif

1
Ken Chen
iT邦新手 4 級 ‧ 2021-09-18 01:49:44

感謝分享
最近也才稍微讀過一點點 DP 跟 斐波那契 ,覺得還滿有趣的。
讀著讀著還發現其他人可以用另一個方式達成 Time: O(log n) 斐波那契,覺得超酷

Jen iT邦新手 5 級 ‧ 2021-09-19 16:31:33 檢舉

O(log n)也太酷了~
跪求分享!!

Ken Chen iT邦新手 4 級 ‧ 2021-09-19 17:48:59 檢舉

https://link.medium.com/QiNXw7QWFjb

要用到矩陣,覺得這篇寫得很棒

1
TD
iT邦新手 4 級 ‧ 2021-09-18 10:03:05

很棒的解釋和思路的分享!

Jen iT邦新手 5 級 ‧ 2021-09-19 16:32:26 檢舉

謝謝TD的收看 /images/emoticon/emoticon41.gif

我要留言

立即登入留言